#include "wx/wxprec.h"
#include "wx/defs.h"

#if wxUSE_COLLPANE && wxUSE_BUTTON && wxUSE_STATLINE

#include "wx/collpane.h"

#ifndef WX_PRECOMP
#include "wx/toplevel.h"
#include "wx/button.h"
#include "wx/sizer.h"
#include "wx/panel.h"
#endif

#include "wx/statline.h"

const wxChar wxCollapsiblePaneNameStr[] = wxT( "collapsiblePane" );
DEFINE_EVENT_TYPE( wxEVT_COMMAND_COLLPANE_CHANGED )
IMPLEMENT_DYNAMIC_CLASS( wxGenericCollapsiblePane, wxControl )
IMPLEMENT_DYNAMIC_CLASS( wxCollapsiblePaneEvent, wxCommandEvent )

BEGIN_EVENT_TABLE( wxGenericCollapsiblePane, wxControl )
  EVT_BUTTON( wxID_ANY, wxGenericCollapsiblePane::OnButton )
  EVT_SIZE( wxGenericCollapsiblePane::OnSize )
END_EVENT_TABLE()


bool wxGenericCollapsiblePane::Create( wxWindow *parent, wxWindowID id, const wxString& label, const wxPoint& pos,
                                       const wxSize& size, long style, const wxValidator& val, const wxString& name ) {
  if( !wxControl::Create( parent, id, pos, size, style, val, name ) ) {
    return false;
  }
  m_strLabel = label;
  m_pButton = new wxButton( this, wxID_ANY, GetBtnLabel(), wxPoint( 0, 0 ), wxDefaultSize, wxBU_EXACTFIT );
  m_pStaticLine = new wxStaticLine( this, wxID_ANY );
  m_sz = new wxBoxSizer( wxHORIZONTAL );
  m_sz->Add( m_pButton, 0, wxLEFT | wxTOP | wxBOTTOM, GetBorder() );
  m_sz->Add( m_pStaticLine, 1, wxALIGN_CENTER | wxLEFT | wxRIGHT, GetBorder() );
  #if defined(__WXWINCE__) || (defined(__WXGTK__) && !defined(__WXGTK20__))
  SetBackgroundColour( parent->GetBackgroundColour() );
  #endif
  m_pPane = new wxPanel( this, wxID_ANY, wxDefaultPosition, wxDefaultSize,  wxTAB_TRAVERSAL | wxNO_BORDER );
  m_pPane->Hide();
  return true;
}

wxGenericCollapsiblePane::~wxGenericCollapsiblePane() {
  if( m_pButton && m_pStaticLine && m_sz ) {
    m_pButton->SetContainingSizer( NULL );
    m_pStaticLine->SetContainingSizer( NULL );
    wxDELETE( m_sz );
  }
}

wxSize wxGenericCollapsiblePane::DoGetBestSize() const {
  wxSize sz = m_sz->GetMinSize();
  if( IsExpanded() ) {
    sz.SetWidth( wxMax( sz.GetWidth(), m_pPane->GetBestSize().x ) );
    sz.SetHeight( sz.y + GetBorder() + m_pPane->GetBestSize().y );
  }
  return sz;
}

wxString wxGenericCollapsiblePane::GetBtnLabel() const {
  return m_strLabel + ( IsCollapsed() ? wxT( " >>" ) : wxT( " <<" ) );
}

void wxGenericCollapsiblePane::OnStateChange( const wxSize& sz ) {
  SetMinSize( sz );
  SetSize( sz );
  if( this->HasFlag( wxCP_NO_TLW_RESIZE ) ) {
    return;
  }
  wxTopLevelWindow * top = wxDynamicCast( wxGetTopLevelParent( this ), wxTopLevelWindow );
  if( top ) {
    if( top->GetSizer() )
      if( IsCollapsed() )
      { top->GetSizer()->SetSizeHints( top ); }
    if( !top->IsMaximized() ) {
      if( IsCollapsed() ) {
        if( top->GetSizer() ) {
          wxSize sz = top->GetSizer()->CalcMin();
          top->SetClientSize( sz );
        } else {
          top->Layout();
        }
      } else {
        top->Fit();
      }
    }
  }
}

void wxGenericCollapsiblePane::Collapse( bool collapse ) {
  if( IsCollapsed() == collapse ) {
    return;
  }
  m_pPane->Show( !collapse );
  m_pButton->SetLabel( GetBtnLabel() );
  OnStateChange( GetBestSize() );
}

void wxGenericCollapsiblePane::SetLabel( const wxString &label ) {
  m_strLabel = label;
  m_pButton->SetLabel( GetBtnLabel() );
  m_pButton->SetInitialSize();
  Layout();
}

bool wxGenericCollapsiblePane::Layout() {
  if( !m_pButton || !m_pStaticLine || !m_pPane || !m_sz ) {
    return false;
  }
  wxSize oursz( GetSize() );
  m_sz->SetDimension( 0, 0, oursz.GetWidth(), m_sz->GetMinSize().GetHeight() );
  m_sz->Layout();
  if( IsExpanded() ) {
    int yoffset = m_sz->GetSize().GetHeight() + GetBorder();
    m_pPane->SetSize( 0, yoffset,
                      oursz.x, oursz.y - yoffset );
    m_pPane->Layout();
  }
  return true;
}

int wxGenericCollapsiblePane::GetBorder() const {
  #if defined( __WXMAC__ )
  return 6;
  #elif defined(__WXGTK20__)
  return 3;
  #elif defined(__WXMSW__)
  wxASSERT( m_pButton );
  return m_pButton->ConvertDialogToPixels( wxSize( 2, 0 ) ).x;
  #else
  return 5;
  #endif
}

void wxGenericCollapsiblePane::OnButton( wxCommandEvent& event ) {
  if( event.GetEventObject() != m_pButton ) {
    event.Skip();
    return;
  }
  Collapse( !IsCollapsed() );
  wxCollapsiblePaneEvent ev( this, GetId(), IsCollapsed() );
  GetEventHandler()->ProcessEvent( ev );
}

void wxGenericCollapsiblePane::OnSize( wxSizeEvent& ( event ) ) {
  Layout();
}

#endif
